
package is.glif.fenius.translators.argia.utils.auth;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.Proxy;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import org.globus.myproxy.MyProxy;
import org.globus.myproxy.MyProxyException;
import org.ietf.jgss.GSSCredential;


/**
 * This class contains the methods required to log into the appliance and get the GSS credentials
 * from MyProxy.
 * 
 * @author Scott campbell
 * 
 */
public class ApplianceLogin
{
	/** 
	 * GSS Credentails that are returned from My Proxy. This is the proxy certificate
	 * used to call the services with
	 */
	public static GSSCredential credentials = null;

	/**
	 * Log into an appliance. This method will check for and download (if necessary)
	 * the CACert from the server and use it to get a user certificate from My Proxy.
	 * If sucessful, it will store the certificate in the <code>credentials</code> field.
	 * 
	 * @param serverHost host name of server logging into
	 * @param login login id
	 * @param password password
	 * @param proxy a <code>java.net.Proxy</code> object. Use Proxy.NO_PROXY if connected
	 * directly to the internet
	 * @return true if login was successful and the certificate is stored in the credential field
	 * @throws InvocationTargetException
	 */
	public static boolean login(String serverHost, String login, String password, Proxy proxy)
			throws InvocationTargetException
	{
		// Check the CA Certificate
		// Make sure the CA Cert for this host has been downloaded
		if (!getCACert(serverHost, proxy, false)) {
			// Delete the certificate if it was rejected
			return false;
		}

		System.out.println("Trying to log into server " + serverHost);
		MyProxy myProxy = new org.globus.myproxy.MyProxy(serverHost, Constants.MYPROXY_PORT);
		try {
			myProxy.setAuthorization(new org.globus.gsi.gssapi.auth.NoAuthorization());
			credentials = myProxy.get(null, login, password, 26000);
		}
		catch (MyProxyException e) {
			e.printStackTrace();
			throw new InvocationTargetException(e, e.getMessage());
		}

		if(credentials == null)
			System.out.println("Credentials are null");
//		else {
//			System.out.println("Credentials are not null");
//		}
		
		System.out.println("Log in successful, returning GSSCredential");
		return true;
	}
	
	/** 
	 * return the credentials
	 * @return
	 */
	public static GSSCredential getCredentials()
	{
		return credentials;
	}

	/**
	 * Checks to see if the CACert has already been downloaded to the local filesystem. If not, it
	 * will download it.
	 * 
	 * @param host
	 * @param proxy
	 * @return
	 * @throws InvocationTargetException
	 */
	private static boolean getCACert(String host, Proxy proxy, boolean display)
			throws InvocationTargetException
	{
		X509Certificate cert = null;
		// Setup the path locations for the ca certificate
		String userHome = System.getProperty("user.home");

		File localCertPath = new File(userHome + File.separator + Constants.LOCAL_CA_LOCATION);
		String localCertName = host + Constants.CA_SUFFIX;
		String remoteCertPath = "http://" + host + "/" + host + Constants.CA_SUFFIX;
		File fullCertPath = new File(localCertPath, localCertName);

		System.out.println("User Home Path is: " + userHome);
		System.out.println("Cert path is " + localCertPath.getAbsolutePath());
		System.out.println("Cert filename is " + localCertName);
		System.out.println("Remote Cert path is " + remoteCertPath);

		// First check to see if the CA Certificate has been downloaded
		if (!fullCertPath.exists()) {
			System.out.println("Cert does not exist, must download it");

			// create the directory
			localCertPath.mkdirs();
			try {
				FileDownload.download(remoteCertPath, fullCertPath, proxy);
			}
			catch (IOException e) {
				System.out.println("Error getting CA from " + remoteCertPath);
				fullCertPath.delete();
				throw new InvocationTargetException(e, "Error getting CA from " + remoteCertPath);
			}
			if (display) {

				try {
					// Read the certificate and display a dialog to accept it.
					cert = getLocalCertificate(fullCertPath);
				}
				catch (Exception e) {
					e.printStackTrace();
					fullCertPath.delete();
					throw new InvocationTargetException(e,
							"There was an error reading the CA Certificate from the local system");
				}
				// display the certificate in a dialog

				//TODO Must convert this to a java dialog, not an Jface dialog
				
				// display.syncExec(new Runnable() {
				// public void run()
				// {
				// CertificateViewerDialog certDialog = new CertificateViewerDialog(null,
				// serverHost, cert);
				// certDialogResponse = certDialog.open();
				// }
				// });
				// if (certDialogResponse != Window.OK)
				// return false;
			}
		}
		else {
			System.out.println("Cert already exists");
		}

		return true;
	}

	/**
	 * Get the certificate from the local file system
	 * 
	 * @param path
	 * @return
	 * @throws IOException
	 * @throws CertificateException
	 */
	private static X509Certificate getLocalCertificate(File path) throws IOException,
			CertificateException
	{
		InputStream inStream = new FileInputStream(path);
		CertificateFactory cf = CertificateFactory.getInstance("X.509");
		X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
		inStream.close();

		return cert;
	}
}
